/*Scott Rogowski and Yipeng Huang*/
/*smr2167 yh2315*/

#include <stdlib.h>		/* ANSI C standard library */
#include <stdio.h>		/* ANSI C standard input/output library */
#include <stdarg.h>		/* ANSI C standard arguments library */
#include "vpi_user.h"		/* IEEE 1364 PLI VPI routine library  */
#include "assert.h"
#include "misc.h"

#include "pli_interface.h"
#include "params.h"
#include "mipspipe.h"

//Initialize the testbench
int pli_init() {
	int success = get_options();
	if (!success)
		vpi_control(vpiFinish, 1);
	params.cycles = 0;
	clear_input_ports();
	//printf("here"); 
	//set_reset();
	initialize_values();
	return 0;
	// vpi_printf("MADE IT THROUGH PLI_INIT");
	}

//Capture into the port array the values output by the mipspipe
int pli_capture() {
	params.cycles++;

	ports_o.inst_o_valid = get_int_value("bench.dut.inst_o_valid");//scaler
	ports_o.inst_o_addr = get_int_value("bench.dut.inst_o_addr");

	ports_o.data_o_valid = get_int_value("bench.dut.data_o_valid");//scaler
	ports_o.data_o_rw = get_int_value("bench.dut.data_o_rw");//scaler
	ports_o.data_o_addr = get_int_value("bench.dut.data_o_addr");
	ports_o.data_o_value = get_int_value("bench.dut.data_o_value");
	}

//Process the inputs and compare the outputs
int pli_update() {


	update_queues();	
	

	//TODO, the process_... and the set_... were all like process_cam_ and set_cam_ prior.  I thought this redundant.

	// processs DUT outputs, compare against C model

	//Input the valid and request and see if that is what we were expecting
		
	int instruction_match =
	    process_instruction_request(ports_o.inst_o_valid,
					ports_o.inst_o_addr);

	//Input the
	int data_match =
	    process_data_request(ports_o.data_o_valid, ports_o.data_o_rw,
				 ports_o.data_o_addr, ports_o.data_o_value);

	// report errors, if any 
	if (instruction_match != 2)
		vpi_printf("%9lld : %s\n", params.cycles,
			   "Instruction address request mismatch");

	if (data_match != 2)
		vpi_printf("%9lld : %s\n", params.cycles,
			   "Data push or request mismatch");
	
	//If we had an instruction OR a data mismatch, end the program
	int mismatch = 4 - (instruction_match + data_match);
	if (mismatch) {
		vpi_printf("FAILED: Stopped due to %u errors.\n", mismatch);
		//vpi_control(vpiFinish, 1);
		}

	//If we have exceeded our test cycles, passed!
	if (params.cycles >= params.max_cycles) {
		vpi_printf
		    ("PASSED: Test ended after %lld cycles(all checks passed.)\n",
		     params.max_cycles);
		vpi_control(vpiFinish, 1);
		}

	clear_input_ports();

	//Set DUT inputs for next cycle
	set_data();
	set_instruction();
	set_reset();



	
	}

//Drive all of the mips input pins
int pli_drive()
{
	set_scalar_value("bench.dut.reset", ports_i.reset);

	set_scalar_value("bench.dut.inst_i_valid", ports_i.inst_i_valid);
	set_int_value("bench.dut.inst_i", ports_i.inst_i);

	set_scalar_value("bench.dut.data_i_valid", ports_i.data_i_valid);
	set_int_value("bench.dut.data_i", ports_i.data_i);
	}
